import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  ClassSerializerInterceptor,
  UseInterceptors,
} from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { PageQuery } from '../../../util/entity/page.entity';
import { ResetPasswordDto } from './dto/reset-password.dto';
import { HasPerms } from '../../../common/decorator/my.decorator';
import { Perm } from '../../../util/enum/perm.enum';
import { RoleEnum } from '../../../util/enum/role.enum';
import { SetRolesDto } from './dto/set-roles.dto';
import { RoleService } from '../role/role.service';
import { ReqUser } from '../../../common/decorator/user.decorator';
import { QueryUserDto } from './dto/query-user-dto';

@UseInterceptors(ClassSerializerInterceptor)
@Controller()
export class UserController {
  constructor(
    private readonly userService: UserService,
    private readonly roleService: RoleService,
  ) {}

  /**
   * 新增用户
   * @param createUserDto
   */
  @Post()
  @HasPerms(Perm.SysUserAdd)
  async create(@Body() createUserDto: CreateUserDto) {
    return await this.userService.create(createUserDto);
  }

  /**
   * 用户列表:带分页条件查询,也包括通过角色id查询
   * @param pageQuery
   */
  @Post('list')
  findAll(@Body('pageQuery') pageQuery: PageQuery<QueryUserDto>) {
    return this.userService.findAll(pageQuery);
  }

  /**
   * 用户重置密码
   * @param resetPasswordDto
   * @param operatorId
   */

  @HasPerms(Perm.SysUserRePassword)
  @Patch('reset-password')
  async resetPassword(
    @Body() resetPasswordDto: ResetPasswordDto,
    @ReqUser('id') operatorId: number,
  ) {
    const { password, rePassword } = resetPasswordDto;
    await this.userService.checkActions(resetPasswordDto.id, operatorId);
    if (password !== rePassword) {
      throw new Error('两次输入的密码不一样');
    }
    return this.userService.resetPassword(resetPasswordDto);
  }

  /**
   * 用户设置角色
   * root角色无法被选择
   * root用户也无法取消自己的root
   */

  @HasPerms(Perm.SysUserSetRoles)
  @Post('set-roles')
  async setRoles(
    @Body() setRolesDto: SetRolesDto,
    @ReqUser('id') operatorId: number,
  ) {
    await this.userService.checkActions(setRolesDto.id, operatorId);
    const [beIsRoot, isRoot] = await this.userService.areTheyRoot(
      setRolesDto.id,
      operatorId,
    );
    const hasRoot = await this.roleService.hasRootByIds(setRolesDto.roleIds);
    if (!hasRoot && beIsRoot) {
      throw new Error(`${RoleEnum.Root}不能被取消`);
    }
    if (hasRoot && !beIsRoot) {
      throw new Error(`${RoleEnum.Root}不能被选择`);
    }
    if (hasRoot && beIsRoot && isRoot) {
      if (setRolesDto.id !== operatorId) {
        throw new Error(`不能对${RoleEnum.Root}进行任何操作`);
      }
    }
    return this.userService.setRoles(setRolesDto);
  }

  /**
   * 通过用户id获取用户信息
   * @param id
   * @param operatorId
   */

  @HasPerms(Perm.SysUserEdit)
  @Get(':id')
  async getOneById(@Param('id') id: number, @ReqUser('id') operatorId: number) {
    await this.userService.checkActions(id, operatorId);
    return this.userService.getOneByIdOrFail(id);
  }

  /**
   * 更新用户
   * @param id
   * @param updateUserDto
   * @param operatorId
   */

  @HasPerms(Perm.SysUserEdit)
  @Patch(':id')
  async update(
    @Param('id') id: number,
    @Body() updateUserDto: UpdateUserDto,
    @ReqUser('id') operatorId: number,
  ) {
    await this.userService.checkActions(id, operatorId);
    return this.userService.update(id, updateUserDto);
  }

  /**
   * 删除用户,软删除
   * @param id
   * @param operatorId
   */

  @HasPerms(Perm.SysUserDelete)
  @Delete(':id')
  async remove(@Param('id') id: number, @ReqUser('id') operatorId: number) {
    await this.userService.checkActions(id, operatorId);
    return this.userService.remove(id);
  }

  /**
   * 批量删除用户,软删除
   * @param ids
   */

  @HasPerms(Perm.SysUserDelete)
  @Post('batch-delete')
  async batchRemove(@Body('ids') ids: number[]) {
    return this.userService.batchDelete(ids);
  }
  /**
   * 批量添加用户的角色
   * @param ids
   * @param roleIds
   */

  @HasPerms(Perm.SysUserDelete)
  @Post('batch-set-roles')
  async batchSetRoles(
    @Body('ids') ids: number[],
    @Body('roleIds') roleIds: number[],
  ) {
    return this.userService.batchSetRoles(ids, roleIds);
  }
}
